Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | import { eq } from 'drizzle-orm' import { NextResponse } from 'next/server' import { db, schema } from '@/db' import { createEnrollmentRequest, getLinkedParentIds, getTeacherClassroom, isEnrolled, } from '@/lib/classroom' import { getSocketIO } from '@/lib/socket-io' import { getUserId } from '@/lib/viewer' import { withAuth } from '@/lib/auth/withAuth' /** * POST /api/classrooms/[classroomId]/enroll-by-family-code * Teacher looks up a student by family code and creates an enrollment request * * Body: { familyCode: string } * Returns: { success: true, request, player } or { success: false, error } */ export const POST = withAuth(async (req, { params }) => { try { const { classroomId } = (await params) as { classroomId: string } const userId = await getUserId() const body = await req.json() if (!body.familyCode) { return NextResponse.json({ success: false, error: 'Missing familyCode' }, { status: 400 }) } // Verify user is the teacher of this classroom const classroom = await getTeacherClassroom(userId) if (!classroom || classroom.id !== classroomId) { return NextResponse.json({ success: false, error: 'Not authorized' }, { status: 403 }) } // Look up player by family code const normalizedCode = body.familyCode.toUpperCase().trim() const player = await db.query.players.findFirst({ where: eq(schema.players.familyCode, normalizedCode), }) if (!player) { return NextResponse.json( { success: false, error: 'No student found with that family code' }, { status: 404 } ) } // Check if already enrolled const alreadyEnrolled = await isEnrolled(classroomId, player.id) if (alreadyEnrolled) { return NextResponse.json( { success: false, error: 'This student is already enrolled in your classroom', }, { status: 400 } ) } // Create enrollment request (teacher-initiated, requires parent approval) const request = await createEnrollmentRequest({ classroomId, playerId: player.id, requestedBy: userId, requestedByRole: 'teacher', }) // Emit socket event for real-time updates const io = await getSocketIO() if (io) { try { const eventData = { request: { id: request.id, classroomId, classroomName: classroom.name, playerId: player.id, playerName: player.name, requestedByRole: 'teacher', }, } // Emit to classroom channel (for teacher's view) io.to(`classroom:${classroomId}`).emit('enrollment-request-created', eventData) console.log( `[Enroll by Family Code API] Teacher created enrollment request for ${player.name}` ) // Also emit to parent's user channel so they see the pending approval const parentIds = await getLinkedParentIds(player.id) for (const parentId of parentIds) { io.to(`user:${parentId}`).emit('enrollment-request-created', eventData) console.log(`[Enroll by Family Code API] Notified parent ${parentId} of new request`) } } catch (socketError) { console.error('[Enroll by Family Code API] Failed to broadcast:', socketError) } } return NextResponse.json({ success: true, request, player: { id: player.id, name: player.name, emoji: player.emoji, color: player.color, }, }) } catch (error) { console.error('Failed to enroll by family code:', error) return NextResponse.json( { success: false, error: 'Failed to create enrollment request' }, { status: 500 } ) } }) |